home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume90
/
libraris
/
odinlib1
/
part01
/
odin.doc
< prev
next >
Wrap
Text File
|
1990-09-03
|
11KB
|
335 lines
odin.doc, version 1.11, 13-Jul-90, Release 1
Created 3-Jul-90 by Peter Oerbaek
Documentation for odin.library.
The main intention of this library is to provide an easier and more
elaborate support for the multitasking capabilities of the Amiga. The func-
tions are inspired by Linda, an extension-language to C and other
languages, which provides a simple yet efficient multitasking/
multiprocessing API.
The central concept in odin.library is that of the envelope. An envelope
is used to pass information between processes, and they are used to hold
information residing in e-space. In C an envelope is a structure that
begins with the Envelope structure defined in odin.h.
There's no restrictions on the contents of an envelope, the contents being
whatever comes after the Envelope-structure. The contents need not be
contigous in memory. You can specify a C-function to serve as a copying-
routine for each envelope.
The e-space is an abstact storage containing envelopes and their contents.
Envelopes are identified by a name, ie. a null-terminated ASCII string.
Envelopes can be put into and retrieved from e-space via the name.
E-space can contain many envelopes with the same name. Envelopes with the
same name will be retrieved in the same order as they have been inserted
into e-space, forming a queue.
Two envelopes match if their names are equal.
To prevent two different programs from unintentional interference with
each others envelopes a naming convention should be applied. My suggestion
is to name envelopes intended for private use within some internal task
like this: "<ProgramName>:<envelopename>" (this is not used in my
examples...).
Functions for general envelope-management are: CreateEnvelope(),
InitEnvelope() and DisposeEnvelope(). To put envelopes into e-space use:
Out(),CopyOut() or OutEmptyEnvelope(). You can wait for an envelope to
appear in e-space with: In(), Rd() and AwaitNamedEnvelope(). You can also
poll for the existence of envelopes in e-space with: Inp(), Rdp() and
PollNamedEnvelope().
New tasks and processes can be launched by the Eval() function. Eval()
provides a simple, yet powerful way to transfer arguments to the new task/
process, and a way to determine when the new task/process is finished.
There are also two lower-level functions for creating tasks/processes:
StartTask() and StartProcess().
------------------------------------------------------------------------
Function summary
-----------------
------------------------------------------------------------------------
Envelope *InitEnvelope(env,name,len,copyfunc)
D0 A1 A0 D0 A2
Envelope *env;
char *name;
ULONG len;
Envelope *(*copyfunc)();
Initializes env with the name 'name', length of envelope+contents in bytes:
'len', and sets the copyfunc for the envelope to copyfunc.
The Eval() function (e_proc) is not touched.
Returns the newly initialized envelope.
Use the macro NoCopyFunc to specify that the e_copyfunc should be init-
ialized to NULL.
SEE ALSO
CreateEnvelope(), Rd().
------------------------------------------------------------------------
Envelope *In(env)
D0 A1
Envelope *env;
Tries to extract an envelope from e-space with a matching name. If no
envelopes in e-space matches, the caller is put to sleep until a
matching envelope is entered into e-space. The matching envelope is
taken out of e-space and returned. No copying is done.
SEE ALSO
Rd(), Inp(), AwaitNamedEnvelope().
------------------------------------------------------------------------
Envelope *Rd(env)
D0 A1
Envelope *env;
Works like In(), but copies the envelope from e-space to env. If
e_copyfunc of the envelope to be extracted is non-NULL, that function
is used to copy envelope and contents. If copyfunc is NULL the envelope
and contents just after it are copied byte for byte to the location
given by env. No envelope is taken out of e-space.
The copyfunc feature allows complex structures to be copied (eg. binary
trees). A copyfunc should have the following declaration:
Envelope *copy_func(source,target)
Envelope *source,*target;
{ ....
return target;
}
The target-pointer should be returned.
The copyfunc should be made very fast because e-space is locked while
the copying is being done, preventing other tasks from altering e-space.
Rd() returns a pointer to the copy.
SEE ALSO
In(), Rdp().
------------------------------------------------------------------------
void Out(env)
A1
Envelope *env;
Puts env into e-space. This is a non-copying operation, so it is
possible, although NOT recommended, to alter the contents of the
envelope while it is in e-space.
SEE ALSO
CopyOut(), OutEmptyEnvelope().
------------------------------------------------------------------------
void CopyOut(env)
A1
Envelope *env;
Puts a copy of env into e-space. If env->e_copyfunc is non-NULL this
is used to copy the envelope and contents to a newly created envelope
of the same size as env. If e_copyfunc is NULL the envelope is copied
byte for byte.
Use this to put multiple copies of an envelope into e-space.
SEE ALSO
Rd(), Out(), OutEmptyEnvelope().
------------------------------------------------------------------------
struct Task *Eval(env,pri,stacksize,et)
D0 A1 D0 D1 D2
Envelope *env;
long pri,et;
ULONG stacksize;
Eval() creates a new Process or Task (by StartProcess() or StartTask()),
determined by the 'et' parameter. If this parameter is EVAL_PROCESS
a process is started, and if it is EVAL_TASK a task is started.
Eval() passes the envelope 'env' to the new process/task without any
copying. The body of the process is the C-function in env->e_proc.
This should have the following declaration:
Envelope *new_process(passed_env)
Envelope *passed_env;
{ ... }
The stacksize of the new process/task is set to 'stacksize' bytes, and
the process/task gets the priority 'pri'.
The name of the new process becomes the name of the passed envelope.
When the body-function returns an envelope, this envelope is put into
e-space with an Out()-call just before the task/process dies. This can
be used for syncronization between tasks. Be warned though! The system
will panic if the function does in fact NOT return an envelope.
If NULL is returned from the body-function, the process/task just dies,
and nothing is added to e-space.
Eval() carries all registers over to the new task/process except
A7 and A2!.
Eval() returns a pointer to the Task structure of the new process/task,
or NULL if something goes wrong.
SEE ALSO
CreateProcess(), Out(), CreateTask().
------------------------------------------------------------------------
Envelope *Inp(env)
D0 A1
Envelope *env;
Works like In(), but instead of waiting when no matching envelope exists
in e-space, NULL is returned immediately. This corresponds to a kind of
polling.
SEE ALSO
In(), Rdp(), PollNamedEnvelope().
------------------------------------------------------------------------
Envelope *Rdp(env)
D0 A1
Envelope *env;
Works like Rd(), but doesn't wait for a matching envelope, instead NULL
is returned.
SEE ALSO
Inp(), Rd().
------------------------------------------------------------------------
struct Task *StartTask(proc,name,pri,stacksize)
D0 A0 A1 D0 D1
void (*proc)();
char *name;
long pri;
ULONG stacksize; /* stack size in bytes, must be even */
This allocates a stack, and a Task structure, and starts a new task to
execute proc. All registers except the stackpointer are carried over to
the new task. This is necessary since many compilers use register-
relative addressing to access global variables.
When the procedure returns, the task dies.
A pointer to the newly created Task is returned, or NULL if something
goes wrong.
SEE ALSO
StartProcess(), Eval().
------------------------------------------------------------------------
struct Process *StartProcess(proc,name,pri,stacksize)
D0 A0 A1 D0 D1
void (*proc)();
char *name;
long pri;
ULONG stacksize; /* size is in bytes */
As above, just creates a Process instead.
Proc does not have to be at the start of a segment or lie on a 4-byte
boundary.
The process structure and stack are automatically freed when the process
dies by returning or calling Exit(). The code is NOT unloaded.
NB. Returns a pointer to the real Process-struct ie. not the messageport
in it.
SEE ALSO
StartTask(), Eval().
------------------------------------------------------------------------
Envelope *AwaitNamedEnvelope(name)
D0 A0
char *name;
AwaitNamedEnvelope creates a temporary envelope with the name 'name',
and waits for a matching envelope to appear in e-space. When and if a
matching envelope appears, it is taken out of e-space and returned.
The temporary envelope is disposed of.
Use this instead of In().
SEE ALSO
In().
------------------------------------------------------------------------
Envelope *PollNamedEnvelope(name)
D0 A0
char *name;
PollNamedEnvelope() checks if an envelope with the given name exists
in e-space, and if so, it takes it out of e-space and returns it. If
no envelope with the given name exists in e-space NULL is returned
immediately.
This is actually a combination of InitEnvelope() and Inp().
SEE ALSO
Inp().
------------------------------------------------------------------------
void OutEmptyEnvelope(name)
A0
char *name;
OutEmptyEnvelope() creates an empty envelope, with CreateEnvelope(),
gives it the name 'name' and puts it into e-space with Out().
This could be used for simple synchronization.
SEE ALSO
Out().
------------------------------------------------------------------------
Envelope *CreateEnvelope(name,size)
D0 A0 D0
char *name;
ULONG size;
CreateEnvelope() creates a new envelope using AllocMem(). Size is the
byte-size of the envelope+contents. Eg.
struct FilledEnv {
Envelope env;
struct Image img;
};
struct FilledEnv *fe;
....
fe = (struct FilledEnv *)CreateEnvelope("imageenvelope",
(long)sizeof(struct FilledEnv));
The new envelope is initialized with InitEnvelope() to have the given
length, and no copyfunc or proc.
If there is not enough memory for the creation, NULL is returned.
SEE ALSO
DisposeEnvelope(), InitEnvelope().
------------------------------------------------------------------------
void DisposeEnvelope(env)
A1
Envelope *env;
DisposeEnvelope() frees the space taken up by the envelope, by using
FreeMem().
If NULL is passed to this routine nothing is done. This can be used
eg. like this:
....
do { DisposeEnvelope(p = PollNamedEnvelope(name)) } while(p);
....
SEE ALSO
CreateEnvelope().